import json
import struct
from pyglet.gl import *

class LevelLoader(object):
	def __init__(self):
		pass
	
	def loadLevelJSON(self, file):
		jsonData=open(file)
		data = json.load(jsonData)
		jsonData.close()
		return data


#Triangle - assist in loading models from 3d files
class _Triangle:
	points = None
	normal = None

	def __init__(self, p1, p2, p3, n=None):
		self.points = p1, p2, p3 #triangle coords
		
		#Calculate the normal
		p1 = self._calcVector(self.points[2], self.points[1])
		p2 = self._calcVector(self.points[2], self.points[0])
		#cross product
		self.normal = p1[1]*p2[2] - p2[1]*p1[2], p1[2]*p2[0] - p2[2]*p1[0], p1[0]*p2[1] - p2[0]*p1[1]
  
	#calculate vector / edge
	def _calcVector(self, p1, p2):
		x=0
		y=1
		z=2
		return -p1[x] + p2[x], -p1[y] + p2[y], -p1[z] + p2[z]

#ModelLoader - temporarily used to load 3d files into a GL list
class ModelLoader:
	model = 0
	
	#_getTriangles - Yield triangle faces for iterator
	def _getTriangles(self):
		if self.model:
			for face in self.model:
				yield face
	
	#loadList - store the vertices in a list, return the ID
	def loadList(self, id=0):
		x = 0
		y = 1
		z = 2
		listId = glGenLists(1) if not id else id
		glNewList(listId, GL_COMPILE)
		glBegin(GL_TRIANGLES)
		for tri in self._getTriangles():
			glNormal3f(tri.normal[x], tri.normal[y], tri.normal[z])
			glVertex3f(tri.points[0][x], tri.points[0][y], tri.points[0][z])
			glVertex3f(tri.points[1][x], tri.points[1][y], tri.points[1][z])
			glVertex3f(tri.points[2][x], tri.points[2][y], tri.points[2][z])
		glEnd()
		glEndList()
		return listId
	
	#loadStlText - build model from text .stl file
	def loadStlText(self, filename):
		self.model = []
		fp = open(filename, 'r')
		
		for line in fp.readlines():
			words = line.split()
			if len(words) > 0:
				if words[0] == 'solid':
					self.name = words[1]
				
				elif words[0] == 'facet':
					center = [0.0, 0.0, 0.0]
					triangle = []
					normal = (eval(words[2]), eval(words[3]), eval(words[4]))
				
				elif words[0] == 'vertex':
					triangle.append((eval(words[1]), eval(words[2]), eval(words[3])))
				
				elif words[0] == 'endloop':
					if len(triangle) == 3:
						self.model.append(Triangle(triangle[0], triangle[1], triangle[2], normal))
		fp.close()
	
	#loadStlBinary - build model from binary .stl file
	def loadStlBinary(self, filename):
		self.model = []
		fp = open(filename, 'rb')
		h = fp.read(80)

		l = struct.unpack('I', fp.read(4))[0]
		count = 0
		while True:
			try:
				v = []
				for x in range(4):
					p = fp.read(12)
					if len(p) == 12:
						v.append((struct.unpack('f', p[0:4])[0], struct.unpack('f', p[4:8])[0], struct.unpack('f', p[8:12])[0]))
				
				if len(v) == 4:
					tri = _Triangle(v[1], v[2], v[3], v[0])
					self.model.append(tri)
				count += 1
				fp.read(2)
				
				if len(p) == 0:
					break
			except EOFError:
				break
		fp.close()	